package org.xiaoyu.feign.core;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.StringUtils;
import org.xiaoyu.feign.core.annotation.FeignServiceRegister;

public class FeignZookeeper implements InitializingBean, DisposableBean{

	private static final Logger log = LoggerFactory.getLogger(FeignServiceRegister.class);

	public static final String FEIGN_ZOOKEEPER_PATH = "/feignService";

	public static final String FEIGN_ZOOKEEPER = "feignZookeeper";

	public static String serviceName;

	public static String serviceUrl;

	private ZooKeeper zooKeeper;

	public static ConcurrentHashMap<String, ArrayList<String>> serviceAndUrl = new ConcurrentHashMap<>();

	public FeignZookeeper(ZooKeeper zooKeeper) {
		this.zooKeeper = zooKeeper;
	}

	public void init() throws KeeperException, InterruptedException {
		if (zooKeeper != null) {
			String path = FEIGN_ZOOKEEPER_PATH;
			if(!StringUtils.isEmpty(serviceName) && !StringUtils.isEmpty(serviceAndUrl)) {
				Stat stat = zooKeeper.exists(path, null);
				if (stat == null) {
					zooKeeper.create(path, "ROOT".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
				}
				String servicePath = path + "/" + serviceName;
				if (zooKeeper.exists(servicePath, null) == null) {
					zooKeeper.create(servicePath, serviceName.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,
							CreateMode.PERSISTENT);
				}
				String serviceIpPath = servicePath + "/" + serviceUrl;
				if (zooKeeper.exists(serviceIpPath, null) == null) {
					zooKeeper.create(serviceIpPath, serviceName.getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE,
							CreateMode.EPHEMERAL);
				} else {
					log.warn("{}-{} is already existed!!!", serviceName, serviceUrl);
				}
			}
			serviceAndUrl.forEach((k, v) -> {
				String sp = path + "/" + k;
				try {
					List<String> ips = zooKeeper.getChildren(sp, new Watcher() {
						@Override
						public void process(WatchedEvent event) {
							try {
								List<String> ips = zooKeeper.getChildren(sp, this);
								serviceAndUrl.put(k, new ArrayList<>(ips));
							} catch (KeeperException | InterruptedException e) {
								e.printStackTrace();
							}
						}
					});
					serviceAndUrl.put(k, new ArrayList<>(ips));
				} catch (KeeperException | InterruptedException e) {
					e.printStackTrace();
				}
			});
		}
	}
	
	public void close() throws InterruptedException {
		if (zooKeeper != null) {
			zooKeeper.close();
		}
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		init();	
	}

	@Override
	public void destroy() throws Exception {
		close();	
	}
	

}
